﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using static QntPlatform.Strategy.TvCmdHandler;

namespace QntPlatform.Strategy
{
 /// <summary>
 /// 趋势做单，只添加固定止损，不设止盈，分为下单、止损两个信号
 /// </summary>
    public class BuyStopSync: StrategyBase
    {

        StrategyBase Parent { get; set; }
        TvCmdHandler tvCmdEx;
        public BuyStopSync(IExchange exchange, ISysFun sysFun, ISysApi sysApi, ITAFun ta) : base(exchange, sysFun, sysApi, ta)
        {
        }
        public BuyStopSync(TvCmdHandler parent):base(parent.Exchange,parent.SysFun,parent.SysApi,parent.TA)
        {
            Parent = parent;
        }
        public override void Init()
        {
            tvCmdEx =    Parent as TvCmdHandler;
            tvCmdEx.cmdFunDic.Add("signSync", signSync);
            tvCmdEx.AutoHandlerDic.Add(nameof(BuyStopSync), AutoOutHandle);
        }
        public void signSync(string cmd) {
          var info=  tvCmdEx.GetCmdValue<Info>(cmd);
            if (!SyncInfo(info))
            {
                return;
            }
            if (info.Direction==SideDirection.Buy)
            {
                InBuy(info);
            }
            else if (info.Direction == SideDirection.Sell)
            {
                InBuy(info,false);
            }
        }
        public void InShort(Info info) { 
        
        }
        public void InBuy(Info info,bool isLong=true) {
                //buy
                var account = Exchange.GetAccountAsync();
                var tck = Exchange.GetTickerAsync();
                var nowPrice = tck.Result.Buy;
                var buyAmount = account.Result.Balance * 0.05m * 20 / nowPrice;
                var id =isLong? Exchange.BuyAsync(-1, buyAmount): Exchange.SellAsync(-1, buyAmount);
                var auto = new AutoSellOrder();
                auto.SourcePrice = nowPrice;
                //auto.ProfitPrices = cmdVal.sells;
                auto.SourceOrderId = id.Result;
                auto.SourceAmount = buyAmount;
                auto.Amount = buyAmount;
                auto.Direction =isLong? SideDirection.CloseBuy:SideDirection.CloseSell;
                auto.StopLossPrice = info.StopLoss.Value; ;
                ///todo 需特殊处理
                auto.HandlerType = nameof(BuyStopSync); // this.GetType().Name;
               tvCmdEx.autoSellOrders.Add(auto);
        }
        public bool AutoOutHandle(Ticker tck, TvCmdHandler.AutoSellOrder autoSellOrder) {
            if (ISysFun.calcUnitProfit(tck.Buy, autoSellOrder.StopLossPrice,autoSellOrder.Direction== SideDirection.CloseBuy) <0)
            {
                tvCmdEx.execTrade(autoSellOrder.Direction, autoSellOrder.Amount);
                return true;
            }
            return false;
        }
        int validTime = 3000;
        int timeDiff = 1000;
        decimal priceDiff = 1;
        ILog log = Log.Default();
        public bool SyncInfo(Info info) {
           
            TmpInfo = TmpInfo.Where(p => p.Sign.Value.AddMilliseconds(validTime) > DateTimeOffset.Now).ToList();
           var re= TmpInfo.FirstOrDefault(p=> {
                //时间相差在1s以内
                if (Math.Abs((info.Time-p.Time).Value.TotalMilliseconds)> timeDiff)
                {
                    return false;
                }
                //价格相差在1元内
                if (Math.Abs(info.Price.Value-p.Price.Value)>priceDiff)
                {
                    return false;
                }
                //合并数据
                if (info.StopLoss!=null&&p.Direction!=null)
                {
                    info.Direction = p.Direction;
                }
                else if (info.Direction != null && p.StopLoss != null)
                {
                    info.StopLoss = p.StopLoss;
                }
                else
                {
                    return false;
                }
                //清理数据
                return true; ;
            });
            if (re==null)
            {
                info.Sign = DateTimeOffset.Now;
                TmpInfo.Add(info);
                return false;
            }
            else
            {
                TmpInfo.Remove(re);
                return true;
            }
        }
        public override void MainFun()
        {
            
        }

        public List<Info> TmpInfo = new List<Info>();

        

        public class Info
        {
            public SideDirection? Direction { get; set; }
            public decimal? Price { get; set; }
            public DateTimeOffset? Time { get; set; }
            public decimal? StopLoss { get; set; }
            internal DateTimeOffset? Sign { get; set; }
        }
    }
}
